<template>
  <div class="rt-wrapper">
    <!--------------------------------------- 表格行搜索配置 -------------------------------------------->
    <div class="rt-header">
      <SearchWrapper
        v-if="JSON.stringify(_searchConfig.itemsMap) !== '{}'"
        :search-config="_searchConfig.itemsMap"
        @onSubmit="_handleSearch"
      />
      <slot name="page-operations" />
    </div>
    <div class="rt-content">
      <!-- 表格组件 -->
      <el-table
        ref="table"
        :data="list"
        v-bind="_elTable"
        @sort-change="_handleSortChange"
        @selection-change="_handleChange"
      >
        <!---------------------------------- 表格行单选或者多选配置 ------------------------------------->
        <!-- 支持表格行单选 -->
        <el-table-column
          v-if="_elTable.selectiveType === 'radio'"
          label="选择"
          width="80"
          align="center"
        >
          <template slot-scope="scope">
            <el-radio
              v-model="currId"
              :label="scope.row[_elTable.rowKey]"
              @change="_handleChange"
            ><i /></el-radio>
          </template>
        </el-table-column>
        <!-- 支持表格行多选 -->
        <template v-if="_elTable.selectiveType === 'checkbox'" align="center">
          <el-table-column type="selection" reserve-selection />
        </template>
        <!--------------------------------------- 表格内容配置 ------------------------------------------>
        <template v-for="(item, index) in _columns">
          <!-- 启用插槽 -->
          <el-table-column v-if="item.slot" :key="index" v-bind="item">
            <template v-slot="scope">
              <slot :name="item.prop" :row="scope.row" />
            </template>
          </el-table-column>
          <!-- 不使用插槽 -->
          <el-table-column v-else :key="index" v-bind="item" />
        </template>
        <!----------------------------------------- 行按钮配置 -------------------------------------------->
        <el-table-column v-if="_elTable.btnsGroup" align="center" label="操作">
          <template slot-scope="scope">
            <template v-for="(item, index) in _calcBtns(scope.row)">
              <!-- 删除按钮 -->
              <el-popconfirm
                v-if="item.type === 'delete'"
                :key="index"
                icon="el-icon-info"
                icon-color="red"
                :title="
                  item.deleteTip ? item.deleteTip : '您确定要删除本条数据吗？'
                "
                @onConfirm="_handleClick(item, scope.row)"
              >
                <el-button
                  slot="reference"
                  style="margin-left: 10px; color: red"
                  type="text"
                  size="mini"
                >{{ item.label }}</el-button>
              </el-popconfirm>
              <!-- 常规按钮 -->
              <el-button
                v-else
                :key="index"
                size="mini"
                type="text"
                @click="_handleClick(item, scope.row)"
              >{{ item.label }}</el-button>
            </template>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <!-------------------------------------------- 表格行分页配置 ------------------------------------------->
    <div v-if="_elPagination.show" class="rt-footer">
      <el-pagination
        v-bind="_elPagination"
        :total="total"
        :page-size="_pageSize"
        :current-page.sync="currPage"
        @current-change="_handlePageChange"
      />
    </div>
  </div>
</template>

<script>
import SearchWrapper from '../SearchWrapper'
export default {
  components: {
    SearchWrapper
  },
  props: {
    // 搜索条件配置
    searchConfig: {
      type: Object,
      default() {
        return {}
      }
    },
    // table 相关配置
    elTable: {
      type: Object,
      default() {
        return {}
      }
    },
    // 分页器相关配置
    elPagination: {
      type: Object,
      default() {
        return {}
      }
    },
    // 异步数据相关配置
    asyncData: {
      type: Object,
      default() {
        return {}
      }
    }
  },
  data() {
    return {
      // 搜索条件
      searchParams: {},
      // 表格数据
      list: [],
      // 当前页码
      currPage: 1,
      // 列表总条数
      total: 0,
      // 选中行数据标识字段
      currId: null,
      // 选中的多行数据
      multipleSelection: []
    }
  },
  computed: {
    _columns() {
      return this._elTable['columns'].map((col) => {
        if (!col.formatter) {
          col.formatter = (row, col, cell) => {
            return cell === null || cell === undefined ? '-' : cell
          }
        }
        col.align = col.align || 'center'
        return col
      })
    },
    _searchConfig() {
      const defaultVal = {
        // 搜索回调函数
        cb(val) {
          return val
        },
        // 表单项配置
        itemsMap: {}
      }
      return Object.assign({}, defaultVal, this.searchConfig)
    },
    _elTable() {
      const defaultVal = {
        // 表格列属性配置
        columns: [],
        /**
         * 表格行操作按钮
         * 数组类型
         * Array :[{label:'详情',type:'info'}]
         * 函数类型
         * Function:function(row){
         *  return [{label:'详情',type:'info'}]
         * }
         */
        // eslint-disable-next-line vue/require-default-prop
        btnsGroup: {
          type: [Array, Function]
        },
        // 行数据key selectiveType !==null 时，必须提供
        rowKey: undefined,
        /**
         * 是否支持选择行数据
         * selectiveType  null (不支持选择) | radio (单选) |checkbox | (多选)
         */
        border: true,
        style: 'width: 100%',
        selectiveType: null
      }
      return Object.assign({}, defaultVal, this.elTable)
    },
    _elPagination() {
      const defaultVal = {
        // 是否显示
        show: true,
        background: true,
        layout: 'total, prev, pager, next,jumper'
      }
      return Object.assign({}, defaultVal, this.elPagination)
    },
    _asyncData() {
      const defaultVal = {
        // 是否需要做初始化请求
        isInitial: true,
        // 列表数据异步请求api
        api: null,
        // api 请求参数
        query: {},
        // 异步请求完毕后回调函数
        cb: function(res) {
          return res
        }
      }
      return Object.assign({}, defaultVal, this.asyncData)
    },
    _pageSize() {
      const { pageSize = 10 } = this._asyncData.query
      return pageSize
    }
  },
  async created() {
    const { isInitial } = this._asyncData
    if (isInitial) {
      await this.queryList()
    }
    console.log('配置项数据', this.$options)
  },
  methods: {
    // 判断表格行显示内容
    _calcBtns(row) {
      const btnsGroup = this._elTable.btnsGroup
      if (typeof btnsGroup === 'function') {
        return btnsGroup(row) || []
      }
      return btnsGroup
    },
    // 搜索
    _handleSearch(searchParams) {
      this.currPage = 1
      const beforeSearch = this.searchConfig.beforeSearch
      this.searchParams = beforeSearch ? (beforeSearch(searchParams) || {}) : searchParams
      this.queryList()
    },
    // 分页
    _handlePageChange(page) {
      this.currPage = page
      this.queryList()
    },

    // 行按钮点击事件
    _handleClick(item, row) {
      this.$emit('tap', {
        btn: item,
        rowInfo: row
      })
    },

    // 表格字段排序
    _handleSortChange(sortInfo) {
      const { order, prop } = sortInfo
      const orderMap = { descending: false, ascending: true }
      this.searchParams['orderField'] = order ? prop : null
      this.searchParams['isAscend'] = order ? orderMap[order] : null
      this.queryList()
    },

    /**
     * 选择表格行
     * @param {String} ids (单选时，为行数据唯一标识，多选时为行数)
     */
    _handleChange(ids, id) {
      this.$emit('handleSelect', ids)
    },

    // 获取表格实例对象
    getTable() {
      return this.$refs['table']
    },

    // 数据列表请求
    async queryList() {
      try {
        const { api, query, cb } = this._asyncData
        if (!api) return
        const defaultParams = {
          pageIndex: this.currPage,
          pageSize: this._pageSize
        }
        const response = await api({
          ...defaultParams,
          ...query,
          ...this.searchParams
        })
        const { result } = cb(response)
        if (result) {
          const { data, totalSize } = result
          this.list = data
          this.total = totalSize
          // 解决当前页数据被清空后，没有自动请求上一页数据的问题
          if (Array.isArray(data) && data.length === 0) {
            if (this.currPage >= 2) {
              this.currPage -= 1
              this.queryList()
            }
          }
          return
        }
      } catch (error) {
        console.error(error)
      }
    }
  }
}
</script>

<style scoped lang="scss">
@mixin flex($justify-content: center, $align-items: center, $flex-direction: row) {
  display: flex;
  justify-content: $justify-content;
  align-items: $align-items;
  flex-direction: $flex-direction;
}
.rt-header {
  @include flex(space-between, center);
  margin-bottom: 15px;
}
.rt-footer {
  @include flex(flex-end, center);
  margin: 30px 0;
}
</style>
